/* ************************************************************************** *
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.
 * 
 * This file is licensed to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * ************************************************************************** */
package org.statewalker.core;

/**
 * @author kotelnikov
 */
public interface IState {

    /**
     * Instances of this type are used in the
     * {@link IState#activate(IEvent, ICallback)} and
     * {@link IState#deactivate(IEvent, ICallback)} methods to notify that state
     * activation/de-activation is finished. These callbacks are created by the
     * core running the process and they should not be instantiated manually.
     * 
     * @author kotelnikov
     */
    interface ICallback {
        /**
         * This method is called by each state to notify that the state was
         * activated/deactivated.
         * 
         * @param event the event created by the state; this event will be used
         *        by the process to define the next target states
         */
        void finish(IEvent event);
    }

    /**
     * This method is called to activate this state. The implementation of this
     * method has to call the given callback object to notify that the process
     * could be continued. Note that if the {@link ICallback#finish(IEvent)}
     * method is not called then the process will be hanged out forever.
     * 
     * @param event the event which triggered transition in this state
     * @param callback the callback object; it is used to notify when this
     *        method is finished
     */
    void activate(IEvent event, ICallback callback);

    /**
     * This method is called to de-activate this state. The implementation of
     * this method has to call the given callback object to notify that the
     * process could be continued. Note that if the
     * {@link ICallback#finish(IEvent)} method is not called then the process
     * will be hanged out forever.
     * 
     * @param event the event which triggered transition in this state
     * @param callback the callback object; it is used to notify when this
     *        method is finished
     */
    void deactivate(IEvent event, ICallback callback);

    /**
     * Returns the context associated with the process
     * 
     * @return the context associated with the process
     */
    IProcessContext getContext();

    /**
     * Returns the key of this state.
     * 
     * @return the key of this state
     */
    String getKey();

    /**
     * Returns the parent state in the process stack.
     * 
     * @return the parent state
     */
    IState getParent();

    /**
     * This method is called to notify about transitions between two sub-states.
     * When this method is called the previous sub-state is already deactivated
     * and the next state is not activated yet.
     * 
     * @param prev the previous sub-state; this state is <code>null</code> if
     *        the FSM enters in the current state
     * @param event the event activating the transition
     * @param next the next sub-state; this state is <code>null</code> when the
     *        FSM goes out of this state
     */
    void onTransition(IState prev, IEvent event, IState next);

    /**
     * Sets the process context for this state. This method is called before the
     * {@link #activate(IEvent, ICallback)} method.
     * 
     * @param context the context to set
     */
    void setContext(IProcessContext context);

    /**
     * Sets the key of this state. This method is called before the
     * {@link #activate(IEvent, ICallback)} method.
     * 
     * @param stateKey the state key
     */
    void setKey(String stateKey);

    /**
     * Sets the parent for this state. This method is called before the
     * {@link #activate(IEvent, ICallback)} method.
     * 
     * @param parent the parent state for this state.
     */
    void setParent(IState parent);

}